#pragma once

#include "Common.hpp"
#include "SocketTemplate.hpp"
#include "IOservice.hpp"
#include "Reactor.hpp"
#include "Protocol.hpp"
#include "Calculator.hpp"

using namespace SocketModule;

// 专门用来处理listensockfd的
// 链接管理模块
class Listenner : public Connection
{
public:
    Listenner(uint16_t port)
        :_port(port)
        ,_listensock(std::make_unique<TcpSocket>())
    {
        _listensock->BuildTcpSocketMethod(_port);
        // 初始化sockfd
        SetSockfd(_listensock->Fd());
        // 初始化关心的事件
        SetEvents(EPOLLIN | EPOLLET);
    }

    // 直接在这里设置回调函数
    virtual void Sender() override
    {}

    // 重写listensockfd的读方法，其他的方法不关心，这样就不需要Accepter方法了
    virtual void Recver() override
    {
        // 到了这里，说明listensockfd就绪了，所以不用等待，我们要进行的是获取新连接处理
        // 但是你怎么知道，一次来的就是一个连接呢？你怎么保证一次读完连接了呢？
        // 所以我们设置以ET模式处理这个listensockfd，而且ET模式下，listensockfd必须是非阻塞的，所以要进行设置
        while(true)
        {
            InetAddr peer;
            int aerrno;
            int sockfd = _listensock->Accepter(&peer, &aerrno);
            if(sockfd > 0)
            {
                // success
                // 不能直接读取新获取到的sockfd，要将sockfd添加到epoll中，让epollserver来管理，而且epollserver只认Connection对象
                LOG(LogLevel::DEBUG) << "Accept success: " << sockfd;
                // 现在要做的事情就是，处理普通的文件描述符！普通sockfd是用来处理IO的，普通文件描述符对于epollserver也是一个Connection
                // 1. 设置文件描述符非阻塞
                SetNonBlock(sockfd);
                // 2. sockfd包装成Connection对象
                auto conn = std::make_shared<IOservice>(sockfd);
                // 3. 注册回调函数
                conn->RigesterOnMessage(HandlerRequest);
                // 4. 将链接插入到epollserver中，通过指向自己的指针
                GetOwner()->InsertConnection(conn);
                
            }
            else
            {
                // 失败了，错误码会被设置，在错误码中我们又需要细分错误的信息，也就是失败的结果有很多种：
                // 典型的就是由于缓冲区的数据读完了，也就是连接读取完了而返回的失败
                // 还有一种可能就是被信号中断了返回的失败
                // 最后一种就是真的失败了
                if(aerrno == EAGAIN || aerrno == EWOULDBLOCK)  // 说明是连接获取完毕了才错误的
                {
                    LOG(LogLevel::DEBUG) << "accepter all connections.... done";
                    break;
                }
                else if(aerrno == EINTR)  // 说明是被信号中断的
                {
                    LOG(LogLevel::DEBUG) << "accepter interupted by signal... continue";
                    continue;
                }
                else   // 真的错了
                {
                    LOG(LogLevel::WARNING) << "accepter failed... ignore";
                    break;
                }
            }
        }
    }

    virtual void Excepter() override
    {}

    // void Accepter()
    // {
        
    // }

    int Sockfd()
    {
        return _listensock->Fd();
    }

    ~Listenner()
    {
        _listensock->Close(); 
    }
private:
    uint16_t _port;
    std::unique_ptr<Socket> _listensock;  // socket套接字
};